//
// DotNetNuke - http://www.dotnetnuke.com
// Copyright (c) 2002-2010
// by Perpetual Motion Interactive Systems Inc. ( http://www.perpetualmotion.ca )
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Services.Cache;

namespace DotNetNuke.Services.EventQueue.Config
{
	internal class EventQueueConfiguration
	{
		private Dictionary<string, PublishedEvent> _publishedEvents;
		private Dictionary<string, SubscriberInfo> _eventQueueSubscribers;
		internal EventQueueConfiguration()
		{
			_publishedEvents = new Dictionary<string, PublishedEvent>();
			_eventQueueSubscribers = new Dictionary<string, SubscriberInfo>();
		}
		internal Dictionary<string, SubscriberInfo> EventQueueSubscribers {
			get { return _eventQueueSubscribers; }
			set { _eventQueueSubscribers= value; }
		}
		internal Dictionary<string, PublishedEvent> PublishedEvents {
			get { return _publishedEvents; }
			set { _publishedEvents= value; }
		}
		private void Deserialize(string configXml)
		{
			if (!String.IsNullOrEmpty(configXml)) {
				XmlDocument xmlDoc = new XmlDocument();
				xmlDoc.LoadXml(configXml);
				foreach (XmlElement xmlItem in xmlDoc.SelectNodes("/EventQueueConfig/PublishedEvents/Event")) {
					PublishedEvent oPublishedEvent = new PublishedEvent();
					oPublishedEvent.EventName = xmlItem.SelectSingleNode("EventName").InnerText;
					oPublishedEvent.Subscribers = xmlItem.SelectSingleNode("Subscribers").InnerText;
					this.PublishedEvents.Add(oPublishedEvent.EventName, oPublishedEvent);
				}
				foreach (XmlElement xmlItem in xmlDoc.SelectNodes("/EventQueueConfig/EventQueueSubscribers/Subscriber")) {
					SubscriberInfo oSubscriberInfo = new SubscriberInfo();
					oSubscriberInfo.ID = xmlItem.SelectSingleNode("ID").InnerText;
					oSubscriberInfo.Name = xmlItem.SelectSingleNode("Name").InnerText;
					oSubscriberInfo.Address = xmlItem.SelectSingleNode("Address").InnerText;
					oSubscriberInfo.Description = xmlItem.SelectSingleNode("Description").InnerText;
					oSubscriberInfo.PrivateKey = xmlItem.SelectSingleNode("PrivateKey").InnerText;
					this.EventQueueSubscribers.Add(oSubscriberInfo.ID, oSubscriberInfo);
				}
			}
		}

		public static void RegisterEventSubscription(EventQueueConfiguration config, string eventname, SubscriberInfo subscriber)
		{
			PublishedEvent e = new PublishedEvent();
			e.EventName = eventname;
			e.Subscribers = subscriber.ID;
			config.PublishedEvents.Add(e.EventName, e);
			if (!config.EventQueueSubscribers.ContainsKey(subscriber.ID))
			{
				config.EventQueueSubscribers.Add(subscriber.ID, subscriber);
			}
		}

		private string Serialize()
		{
			XmlWriterSettings settings = new XmlWriterSettings();
			settings.ConformanceLevel = ConformanceLevel.Document;
			settings.Indent = true;
			settings.CloseOutput = true;
			settings.OmitXmlDeclaration = false;
			StringBuilder sb = new StringBuilder();
			XmlWriter writer = XmlWriter.Create(sb, settings);
			writer.WriteStartElement("EventQueueConfig");
			writer.WriteStartElement("PublishedEvents");
			foreach (string key in this.PublishedEvents.Keys) {
				writer.WriteStartElement("Event");
				writer.WriteElementString("EventName", this.PublishedEvents[key].EventName);
				writer.WriteElementString("Subscribers", this.PublishedEvents[key].Subscribers);
				writer.WriteEndElement();
			}
			writer.WriteEndElement();
			writer.WriteStartElement("EventQueueSubscribers");
			foreach (string key in this.EventQueueSubscribers.Keys) {
				writer.WriteStartElement("Subscriber");
				writer.WriteElementString("ID", this.EventQueueSubscribers[key].ID);
				writer.WriteElementString("Name", this.EventQueueSubscribers[key].Name);
				writer.WriteElementString("Address", this.EventQueueSubscribers[key].Address);
				writer.WriteElementString("Description", this.EventQueueSubscribers[key].Description);
				writer.WriteElementString("PrivateKey", this.EventQueueSubscribers[key].PrivateKey);
				writer.WriteEndElement();
			}
			writer.WriteEndElement();
			writer.WriteEndElement();
			writer.Close();
			return sb.ToString();
		}
		static internal EventQueueConfiguration GetConfig()
		{
			EventQueueConfiguration config = (EventQueueConfiguration)DataCache.GetCache("EventQueueConfig");
			if ((config == null)) {
				string filePath = DotNetNuke.Common.Globals.HostMapPath + "EventQueue\\EventQueue.config";
				if (File.Exists(filePath)) {
					config = new EventQueueConfiguration();
					config.Deserialize(FileSystemUtils.ReadFile(filePath));
					//Set back into Cache
					DataCache.SetCache("EventQueueConfig", config, new DNNCacheDependency(filePath));
				} else {
					config = new EventQueueConfiguration();
					config.PublishedEvents = new Dictionary<string, PublishedEvent>();
					config.EventQueueSubscribers = new Dictionary<string, SubscriberInfo>();
					SubscriberInfo subscriber = new SubscriberInfo("DNN Core");
                    RegisterEventSubscription(config, "Application_Start", subscriber);
					RegisterEventSubscription(config, "Application_Start_FirstRequest", subscriber);
					SaveConfig(config, filePath);
				}
			}
			return config;
		}

		internal static void SaveConfig(EventQueueConfiguration config, string filePath)
		{
			StreamWriter oStream = File.CreateText(filePath);
			oStream.WriteLine(config.Serialize());
			oStream.Close();
			//Set back into Cache
			DataCache.SetCache("EventQueueConfig", config, new DNNCacheDependency(filePath));
		}
	}
}
